/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
/* $Id: email.c 3 2007-07-10 06:59:05Z kf701.ye $ */

#include <sys/types.h>
#include <sys/socket.h>

#include "factory.h"

#define CONTENT_TYPE	"Content-Type: multipart/mixed; boundary=\"" EMAIL_BOUNDARY "\""	  
#define FIRST_BODY	"--" EMAIL_BOUNDARY "\r\nContent-Type: text/plain;charset=" EMAIL_CHARSET \
			"\r\nContent-Transfer-Encoding: 7bit\r\n\r\n"
/**
 * @brief send mail without attach file
 */
bool send_mail(mail_t *mail)
{
	struct timeval tv;
	int sockfd;
	int i, rt;
	int auth_base64_flag;
	char buffer[10*1024],*ptr,username[EMAIL_MAXLINE];
	bool first_auth = false;
	
	if ( NULL == mail || NULL == mail->smtp || NULL == mail->from || 
		NULL == mail->context || NULL == mail->passwd || NULL == mail->to )
	{
		return false;
	}

	/* get out account name */
	strncpy(username,mail->from,EMAIL_MAXLINE);
        ptr = username;
	while ( *ptr != '@' && *ptr != '\0' )
		ptr++;
	if ( *ptr == '\0' )
		return -1;	 	
	else if ( *ptr == '@' )
		*ptr = '\0';
	else 
		return false;

	sockfd = connect_nonblock(mail->smtp,25,20);
	if (sockfd <= 0)
	{
		goto error;
	}
	
	tv.tv_sec = 10;
	tv.tv_usec = 0;	
	if ( setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) < 0)
	{
		goto error;
	}	
	
	readline2(sockfd,buffer,EMAIL_MAXLINE);
	if ( strncmp(buffer,"220",3) )
	{		
		goto error;
	}

	sprintf(buffer,"EHLO %s\r\n",mail->smtp);
	if (rio_write(sockfd,buffer,strlen(buffer)) < 0)
	{
	 	goto error;
	}
	
	auth_base64_flag = 0;
	do
	{
		rt = readline2(sockfd,buffer,EMAIL_MAXLINE);		
		if (rt <= 0)
		{
			goto error;
		}
		if ( !strncmp("250-AUTH",buffer,8) && strstr(buffer,"LOGIN") )
			auth_base64_flag = 1;
	} while (strncmp(buffer,"250 ",4) != 0) ;
	
	if (auth_base64_flag != 0)
	{
		if ( rio_write(sockfd,"AUTH LOGIN\r\n",12)  < 0 )
			goto error;
		if ( readline2(sockfd,buffer,EMAIL_MAXLINE) < 0)
			goto error;
		if ( 0 != strncmp("334 ",buffer,4) )
			goto error;
		encode_b64((uint8_t*)buffer,(uint8_t*)username,strlen(username));
		strcat(buffer,"\r\n");
		if ( rio_write(sockfd,buffer,strlen(buffer)) < 0)
			goto error;
		if ( readline2(sockfd,buffer,EMAIL_MAXLINE) < 0)
			goto error;
		if ( 0 != strncmp("334 ",buffer,4) )
                {
                       first_auth = false;
                }else
		{
                       first_auth = true;
                } 
 
		encode_b64((uint8_t*)buffer,(uint8_t*)mail->passwd,strlen(mail->passwd) );
		strcat(buffer,"\r\n");
		if ( rio_write(sockfd,buffer,strlen(buffer)) < 0)
			goto error;
		if ( readline2(sockfd,buffer,EMAIL_MAXLINE) < 0)
			goto error;
		if ( 0 != strncmp("235 ",buffer,4) )
                {
                        first_auth = false;
                }else{
                        first_auth = true;
                }
	}
        
        /* the first auth failed , try use the mail->from as the email account */
	if ( auth_base64_flag != 0  && first_auth == false )
	{
		if ( rio_write(sockfd,"AUTH LOGIN\r\n",12)  < 0 )
		{
			goto error;
		}
		if ( readline2(sockfd,buffer,EMAIL_MAXLINE) < 0)
		{
			goto error;
		}
		if ( 0 != strncmp("334 ",buffer,4) )
		{
			goto error;
		}
		encode_b64((uint8_t*)buffer,(uint8_t*)mail->from,strlen(mail->from) );
		strcat(buffer,"\r\n");
		if ( rio_write(sockfd,buffer,strlen(buffer)) < 0)
		{
			goto error;
		}
		if ( readline2(sockfd,buffer,EMAIL_MAXLINE) < 0)
		{
			goto error;
		}
		if ( 0 != strncmp("334 ",buffer,4) )
		{
			goto error;
		}
		
		encode_b64((uint8_t*)buffer,(uint8_t*)mail->passwd,strlen(mail->passwd));
		strcat(buffer,"\r\n");
		if ( rio_write(sockfd,buffer,strlen(buffer)) < 0)
		{
			goto error;
		}
		if ( readline2(sockfd,buffer,EMAIL_MAXLINE) < 0)
		{
			goto error;
		}
		if ( 0 != strncmp("235 ",buffer,4) ) 
		{
			goto error;
		}
	}
	
	sprintf(buffer,"MAIL FROM: <%s>\r\n",mail->from);
	rio_write(sockfd,buffer,strlen(buffer));
	readline2(sockfd,buffer,EMAIL_MAXLINE);
	if (strncmp(buffer,"250",3))
	{
		goto error;
	}

	for( i=0; i<mail->numto; i++ )
	{
		sprintf(buffer,"RCPT TO: <%s>\r\n",mail->to[i]);
		rio_write(sockfd,buffer,strlen(buffer));
		readline2(sockfd,buffer,EMAIL_MAXLINE);
		if (strncmp(buffer,"250",3))
		{
			goto error;
		}
	}
			
	rio_write(sockfd,"DATA\r\n",6);
	readline2(sockfd,buffer,EMAIL_MAXLINE);
	if (strncmp(buffer,"354",3))
	{
		goto error; 
	}	 

	sprintf(buffer,"From: %s\r\n",mail->from);
	if (rio_write(sockfd,buffer,strlen(buffer)) < 0)
		goto error;

	sprintf(buffer,"To: ");
	for(i=0; i<mail->numto; i++)
	{
		strcat( buffer, mail->to[i] );
		strcat( buffer,", ");
	}
	strcat( buffer, "\r\n" );
	if (rio_write(sockfd,buffer,strlen(buffer)) < 0)
		goto error;

	sprintf(buffer,"%s" "\r\n",EMAIL_MIME);
	if (rio_write(sockfd,buffer,strlen(buffer)) < 0)
		goto error;
	
	sprintf(buffer,"Subject: %s\r\n",mail->subject); 
	if (rio_write(sockfd,buffer,strlen(buffer)) < 0)
		goto error;	
	
	sprintf(buffer,"%s\r\n",CONTENT_TYPE);
	if (rio_write(sockfd,buffer,strlen(buffer)) < 0)
		goto error;
	
	sprintf(buffer,"\r\n%s\r\n", "--" EMAIL_BOUNDARY);
	rio_write(sockfd,buffer,strlen(buffer));
	
	sprintf(buffer,"%s",FIRST_BODY);
	rio_write(sockfd,buffer,strlen(buffer)); 

	if (rio_write(sockfd,mail->context,strlen(mail->context)) < 0)
		goto error;
	
	rio_write(sockfd,"\r\n.\r\n",5);
	rio_write(sockfd,"quit\r\n",6);
	close(sockfd);
	return true;	

error:
	close(sockfd);
	return false;	
}
